package com.wyix.state;

import java.util.concurrent.TimeUnit;

/**
 * 线程状态转换演示：快递配送系统
 * 清晰展示线程的6种状态及转换过程
 */
public class ExpressDeliverySimulation {
    // 快递包裹类
    static class Package {
        private final String trackingNumber;
        private String status;

        public Package(String trackingNumber) {
            this.trackingNumber = trackingNumber;
            this.status = "待揽收";
        }

        public void updateStatus(String newStatus) {
            this.status = newStatus;
            System.out.printf("【包裹%s】状态更新: %s\n", trackingNumber, newStatus);
        }

        public String getStatus() {
            return status;
        }
    }

    // 快递员线程类
    static class CourierThread extends Thread {
        private final String courierName;
        private final Package pkg;
        private final Object warehouseLock; // 仓库锁

        public CourierThread(String courierName, Package pkg, Object warehouseLock) {
            super(courierName);
            this.courierName = courierName;
            this.pkg = pkg;
            this.warehouseLock = warehouseLock;
        }

        @Override
        public void run() {
            try {
                // 1. 初始状态: RUNNABLE
                printThreadState("开始工作");
                pkg.updateStatus("快递员已接单");

                // 2. 获取仓库锁: 可能进入BLOCKED状态
                printThreadState("等待进入仓库");
                synchronized (warehouseLock) {
                    printThreadState("进入仓库");
                    pkg.updateStatus("已揽收");
                    work(1500); // 模拟取件时间
                }

                // 3. 运输途中: RUNNABLE
                printThreadState("运输中");
                pkg.updateStatus("运输中");
                work(2000); // 模拟运输时间

                // 4. 定时休息: TIMED_WAITING
                printThreadState("等待红灯");
                pkg.updateStatus("等待交通信号");
                TimeUnit.SECONDS.sleep(2); // 定时等待

                // 5. 等待签收: WAITING
                printThreadState("等待客户签收");
                pkg.updateStatus("已到达目的地，等待签收");
                synchronized (pkg) {
                    pkg.wait(); // 等待签收通知
                }

                // 6. 完成配送: RUNNABLE -> TERMINATED
                printThreadState("完成配送");
                pkg.updateStatus("已签收");

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                pkg.updateStatus("配送异常中断");
                printThreadState("配送中断");
            }
        }

        // 模拟工作时间
        private void work(int millis) throws InterruptedException {
            long endTime = System.currentTimeMillis() + millis;
            while (System.currentTimeMillis() < endTime) {
                // 模拟工作进度
                Thread.yield();
            }
        }

        // 打印线程状态
        private void printThreadState(String action) {
            System.out.printf("【%s】%s: 当前状态=%s\n",
                    courierName, action, getState());
        }
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("===== 快递配送系统启动 ====");

        // 创建包裹和仓库锁
        Package pkg1 = new Package("SF123456789");
        Object warehouseLock = new Object();

        // 创建快递员线程 (初始状态: NEW)
        CourierThread courier = new CourierThread("王快递", pkg1, warehouseLock);
        System.out.printf("【系统】创建快递员线程: %s\n", courier.getState());

        // 启动线程 (状态变为: RUNNABLE)
        courier.start();
        Thread.sleep(500); // 等待线程启动

        // 模拟客户签收流程
        Thread.sleep(8000); // 等待快递员到达
        System.out.println("\n===== 客户准备签收 ====");
        synchronized (pkg1) {
            pkg1.notifyAll(); // 唤醒等待签收的快递员
        }

        // 等待线程结束
        courier.join();
        System.out.printf("\n【系统】快递员线程最终状态: %s\n", courier.getState());
        System.out.println("===== 快递配送系统结束 ====");
    }
}